#define WIN32_LEAN_AND_MEAN
#include <WinSock2.h>
#include <windows.h>
#include <iostream>
#include<map>
#include<time.h>
#pragma warning(disable:4996)
#pragma comment(lib,"ws2_32.lib")

using namespace std;

void split(char* ch, char* username, char* password);

int main()
{
	map<char*, char*> users;
	map<char*, char*> usersall;
	map<int, map<char*, char*>> id_users;
	usersall.clear();
	id_users.clear();
	srand((unsigned)time(NULL));
	int id;
	map<string, string> users0;
	map<string, string> usersall0;
	map<int, map<string, string>> id_users0;
	

	char mode[2];

	

	int iRet;


	WORD ver = MAKEWORD(2, 2);            //使用版本2.2
	WSADATA data;
	iRet = WSAStartup(ver, &data);       //参数
	if (iRet == SOCKET_ERROR)            //error：-1
	{
		cout << "WSAStartup fail" << endl;
	}
	else
	{
		cout << "WSAStartup success" << endl;
	}

	//1、创建套接字
	/*
	SOCKET
	WSAAPI
	socket(
		_In_ int af,			网络ipv4、ipv6
		_In_ int type,			数据类型
		_In_ int protocol		协议 TCP/UDP
	);

	*/
	SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	if (sock == INVALID_SOCKET)
	{
		cout << "SOCKET fail" << endl;
	}
	else
	{
		cout << "SOCKET success" << endl;
	}
	//2、绑定网络端口
	/*
	int
	WSAAPI
	bind(
		_In_ SOCKET s,													socket
		_In_reads_bytes_(namelen) const struct sockaddr FAR * name,
		_In_ int namelen
	 );
	*/
	sockaddr_in sin = {};
	sin.sin_family = AF_INET;
	sin.sin_port = htons(6666);					//host to net  unsigned short
	sin.sin_addr.S_un.S_addr = INADDR_ANY;		//inet_addr("127.0.0.1");
	/*
	typedef struct sockaddr_in {
	#if(_WIN32_WINNT < 0x0600)
		short   sin_family;					网络ipv4、ipv6
	#else //(_WIN32_WINNT < 0x0600)
		ADDRESS_FAMILY sin_family;
	#endif //(_WIN32_WINNT < 0x0600)

		USHORT sin_port;					端口号
		IN_ADDR sin_addr;					ip地址   本机：inet_addr("127.0.0.1")  所有：INADDR_ANY
		CHAR sin_zero[8];
	} SOCKADDR_IN, *PSOCKADDR_IN;
	*/

	iRet = bind(sock, (sockaddr*)&sin, sizeof(sockaddr_in));
	if (iRet == SOCKET_ERROR)
	{
		cout << "bind fail" << endl;
	}
	else
	{
		cout << "bind success" << endl;
	}

	//3、listen监听
	/*
	int
	WSAAPI
	listen(
		_In_ SOCKET s,
		_In_ int backlog		最大允许多少客户端来请求连接
		);

	*/
	iRet = listen(sock, 5);
	if (iRet == SOCKET_ERROR)
	{
		cout << "listen fail" << endl;
	}
	else
	{
		cout << "listen success" << endl;
	}

	//4、accept 等待接收客户端连接
	/*
	SOCKET
	WSAAPI
	accept(
		_In_ SOCKET s,														服务端socket
		_Out_writes_bytes_opt_(*addrlen) struct sockaddr FAR * addr,		客户端socket
		_Inout_opt_ int FAR * addrlen
		);
	*/
	SOCKADDR_IN clientAddr;
	int nAddrLen = sizeof(SOCKADDR_IN);
	while (1)
	{
		SOCKET csock = accept(sock, (SOCKADDR*)&clientAddr, &nAddrLen);

		char* username = new char(10);
		char* password = new char(20);
		string strusername = username;
		string strpassword = password;

		if (csock == INVALID_SOCKET)
		{
			cout << "accept fail" << endl;

			//
			char resbuf[256] = {};
			iRet = recv(sock, resbuf, 256, 0);
			cout << resbuf << endl;
		}
		else
		{
			cout << "accept success" << endl;
	
		}
		cout << "new clint accept:" << inet_ntoa(clientAddr.sin_addr) << endl;    //将sdl设置为否
		//5、send 向客户端发送
		/*
		int
		WSAAPI
		send(
			_In_ SOCKET s,											客户端socket
			_In_reads_bytes_(len) const char FAR * buf,				数据
			_In_ int len,											数据长度
			_In_ int flags											默认0
			);
		*/
	

		
		char resbuf[256] = {};

		iRet = recv(csock, resbuf, 256, 0);
		if (iRet == SOCKET_ERROR)
		{
			cout << "recv fail" << endl;
		}
		else
		{
			cout << "recv success" << endl;
		}
		cout << resbuf<<endl;
		char buf[100] = {};
		split(resbuf, mode, buf);
		split(buf, username, password);
		cout << username << endl;
		cout << password << endl;
		

		if (mode[0] == '1')
		{
			char buf1[11];
			while (id = (rand() % 8999999999) + 1000000000)
			{
				if (id_users.find(id) == id_users.end())
					break;
			}
			itoa(id,buf1,10);
			iRet = send(csock, buf1, strlen(buf1) + 1, 0);
			//users.insert(username, password);
			users.clear();
			users[username] = password;
			usersall[username] = password;
			id_users[id] = users;

			users0.clear();
			users0[username] = password;
			usersall0[username] = password;
			id_users0[id] = users0;

		
			cout << users.size() << endl;
		}
		else
		{
			char ch[] = "admin";
			if (usersall.find(ch) != usersall.end())
			{
				cout << endl << endl;
			}
			//如果找到用户了
			if (usersall0.find(username) != usersall0.end())
			{
				if (usersall0.at(username) == password)
				{
					char buf2[] = "succeeded load";
					iRet = send(csock, buf2, strlen(buf2) + 1, 0);
				}
				else
				{
					char buf2[] = "wrong password";
					iRet = send(csock, buf2, strlen(buf2) + 1, 0);
				}
			}

			else
			{
				char buf3[] = "please input key";
				iRet = send(csock, buf3, strlen(buf3) + 1, 0);

				char resbuf0[256] = {};

				//recieve id
				iRet = recv(csock, resbuf0, 256, 0);
				if (iRet == SOCKET_ERROR)
				{
					cout << "recv fail" << endl;
				}
				else
				{
					cout << "recv success" << endl;
				}
				cout << resbuf0 << endl;

				int i = atoi(resbuf0);

				//find id
				if (id_users.find(i) != id_users.end())
				{
					if (id_users.at(i).size() <= 9)
					{
						users = id_users.at(i);
						users[username] = password;
						usersall[username] = password;
						id_users[i] = users;
						char buf2[] = "succeeded load";
						iRet = send(csock, buf2, strlen(buf2) + 1, 0);
					}

					else
					{
						char buf2[] = "this id if full";
						iRet = send(csock, buf2, strlen(buf2) + 1, 0);
					}

				}

				else
				{
					char buf2[] = "wrong id";
					iRet = send(csock, buf2, strlen(buf2) + 1, 0);

				}
				//
			}
		}
	}
	//6、清除socket环境
	iRet = closesocket(sock);

	if (iRet == SOCKET_ERROR)
	{
		cout << "closesocket fail" << endl;
	}
	else
	{
		cout << "closesocket success" << endl;
	}

	WSACleanup();//清除
	return 0;
}

void split(char* ch, char* username, char* password)
{
	int i = 0;
	int j = 0;
	for (; i <= strlen(ch); i++)
	{
		if (ch[i] == ' ')
		{
			for (int j = 0; j < i; j++)
			{
				username[j] = ch[j];
			}
			username[i] = '\0';
			break;
		}

	}
	i++;
	for (j = 0; i + j < strlen(ch); j++)
	{
		password[j] = ch[i + j];
	}
	password[j] = '\0';
}

bool compare(char* a, char* b)
{
	return strcmp(a, b)==0;
}